<?php
class RBAC{

    static function saveAccessList($roleRs) {
        $admin_role = C('admin_role');
        if( is_array($admin_role) && in_array($roleRs['name'],$admin_role)){
            $_SESSION['_ALL_ACCESS_'] = true;
            return;
        }
        $_SESSION['_ACCESS_LIST_'] = RBAC::getAccessList($roleRs);
    }

    static function getAccessList($roleRs){
        $db_prefix = C('db_prefix');
        $roleTable = "{$db_prefix}role";
        $roleUserTable = "{$db_prefix}user";
        $roleAccessTable = "{$db_prefix}access";
        $roleNodeTable = "{$db_prefix}node";
        $roleName = $roleRs['name'];
        $db = DB::getInstance();
        $sql = "select node.id,node.name,node.pid,node.level from {$roleAccessTable} access left join {$roleNodeTable} node on".
                "node.id=access.nodeId where access.role='{$roleName}' order by node.level asc,node.pid";
        $nodes = $db->query($sql);
        $access = array();
        if(is_array($nodes)){
            $nodesMapping = array();
            foreach($nodes as $node){
                if($node['level'] != '3' && false === array_key_exists($node['id'],$nodesMapping)){
                    $node['name'] = strtoupper($node['name']);
                    $nodesMapping[$node['id']] = $node;
                }else{
                    $moduleNode = $nodesMapping[$node['pid']];
                    $appNode = $nodesMapping[$moduleNode['pid']];
                    $access[$appNode['name']][$moduleNode['name']][strtoupper($node['name'])] = $node['id'];
                }
            }
        }
        return $access;
    }

    static function AccessDecision($appName = APP_NAME){
        //检查是否需要认证
        if(RBAC::checkAccess()) {
            //存在认证识别号，则进行进一步的访问决策
            $accessGuid = md5($appName.MODULE_NAME.ACTION_NAME);
            if($_SESSION['_ALL_ACCESS_']){
				return true;
            }else{
                if(C('USER_AUTH_TYPE')==2){
                    //加强验证和即时验证模式 更加安全 后台权限修改可以即时生效
                    $_SESSION['_ACCESS_LIST_'] = RBAC::getAccessList($_SESSION[C('USER_AUTH_KEY')]['role']);
                }else {
                    // 如果是管理员或者当前操作已经认证过，无需再次认证
                    if( $_SESSION[$accessGuid]) return true;
                }
                $accessList = $_SESSION['_ACCESS_LIST_'];
                //判断是否为组件化模式，如果是，验证其全模块名
                $module = defined('P_MODULE_NAME')?  P_MODULE_NAME   :   MODULE_NAME;
                if(!isset($accessList[strtoupper($appName)][strtoupper($module)][strtoupper(ACTION_NAME)])) {
                    $_SESSION[$accessGuid]  =   false;
                    return false;
                }
                else {
                    $_SESSION[$accessGuid]	=	true;
                }
			}
        }
        return true;
    }

    static function checkAccess(){
        if( C('USER_AUTH_ON') ){
			$_module	=	array();
			$_action	=	array();
            if("" != C('REQUIRE_AUTH_MODULE')) {
                //需要认证的模块
                $_module['yes'] = explode(',',strtoupper(C('REQUIRE_AUTH_MODULE')));
            }else {
                //无需认证的模块
                $_module['no'] = explode(',',strtoupper(C('NOT_AUTH_MODULE')));
            }
            //检查当前模块是否需要认证
            if((!empty($_module['no']) && !in_array(strtoupper(MODULE_NAME),$_module['no'])) || (!empty($_module['yes']) && in_array(strtoupper(MODULE_NAME),$_module['yes']))) {
				if("" != C('REQUIRE_AUTH_ACTION')) {
					//需要认证的操作
					$_action['yes'] = explode(',',strtoupper(C('REQUIRE_AUTH_ACTION')));
				}else {
					//无需认证的操作
					$_action['no'] = explode(',',strtoupper(C('NOT_AUTH_ACTION')));
				}
				//检查当前操作是否需要认证
				if((!empty($_action['no']) && !in_array(strtoupper(ACTION_NAME),$_action['no'])) || (!empty($_action['yes']) && in_array(strtoupper(ACTION_NAME),$_action['yes']))) {
					return true;
				}else {
					return false;
				}
            }else {
                return false;
            }
        }
        return false;
    }

}
